Skip to content

feat: add TransactionDeterministicOrdering() to support deterministic tx generation#344

Closed
JDeuce wants to merge 6 commits intosolana-foundation:mainfrom
JDeuce:feat/deterministicTx
Closed

feat: add TransactionDeterministicOrdering() to support deterministic tx generation#344
JDeuce wants to merge 6 commits intosolana-foundation:mainfrom
JDeuce:feat/deterministicTx

Conversation

@JDeuce
Copy link
Copy Markdown

@JDeuce JDeuce commented Dec 16, 2025

  • When generating tx bytes, map iteration order is used
  • In golang, map iteration order is randomized: see proposal: runtime/map: fix map iteration order golang/go#54500
  • Thus, solana-go library tx bytes are non deterministic due to the random order of accounts generated
  • Non-deterministic generation is not desirable in test environments where exact transaction outputs are being verified
  • This PR seeks to add an option TransactionDeterministicOrdering() which when used, causes the ALTs and addresses within the ALT to be sorted prior to being injected in the TX
  • It is left as optional to minimize friction with getting this change into the upstream, as there is a slight run-time cost associated with sorting the addresses and many use cases do not require deterministic sorting
  • Above reason is why non deterministic ordering is left as the default for now

@JDeuce JDeuce marked this pull request as ready for review December 17, 2025 06:02
@daog1
Copy link
Copy Markdown

daog1 commented Jan 9, 2026

Why don't you just use https://github.com/wk8/go-ordered-map to directly replace this one? I think even without enabling TransactionDeterministicOrdering(), the serialization order should still be deterministic.

@JDeuce
Copy link
Copy Markdown
Author

JDeuce commented Jan 9, 2026

So far, I wanted to start with this initial approach for a few reasons:

  1. Minimize changes to existing behavior and dependencies
    Replacing the current map with something like go-ordered-map would make deterministic ordering always-on and introduce that new dependency for all users. I wanted to preserve current behavior by default and avoid adding a dependency up front.

  2. Keep the change tightly scoped
    The nondeterminism only becomes an issue at the point where address lookup tables are serialized into the transaction message. Addressing it there keeps the fix focused, rather than changing the underlying data structures used throughout transaction construction.

  3. Make the performance tradeoff explicit
    Deterministic ordering has a real (though small) runtime cost due to sorting (current approach), or through sacrifice of native map (e.g. go-ordered-map approach). Making this opt-in ensures that only users who need reproducible transaction bytes (tests, caching, reproducible builds) pay that cost.

I do agree though that, in the long run, it likely makes sense for transaction serialization to be deterministic everywhere by default. This PR is intended as a first, low-friction step in that direction - addressing the immediate need without forcing a broader behavioral or dependency change. With more testing, we could easily make it the default as well.

That being said, happy to switch the PR to a more aggressive approach: including always-sorted ordering or introducing an ordered map dependency... if that’s what would help get this merged

@JDeuce
Copy link
Copy Markdown
Author

JDeuce commented Mar 17, 2026

@daog1 I made an alternate implementation in #364 if you want to take a look

@HealthyBuilder
Copy link
Copy Markdown
Collaborator

Great chat! Thank you for your contribution!

I saw it covered in #365, closing not, Feel free to open new PR if issues remained.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants